//*************************************************************************************************
//************************ (C) 2001 - 2006, Eleven Engineering Incorporated ***********************
//*************************************************************************************************
//**
//**		Tabs:	This file looks best with tab stops set every 6 spaces.
//**
//*************************************************************************************************
//*************************************************************************************************
//**
//**          File:  Math.asm
//**       Project:  XInc2 Library
//**       Created:  04 Jan 2003 by Ryan Northcott
//**       Revised:  08 Sep 2006 by Dan Beutel
//**
//**   Description:  Firmware routines for doing math not available as a single
//**                 XInc2 instruction.
//**
//** Compatibility:  Requires XInA v4.4 or higher.
//**
//**    Disclaimer:  You may incorporate this sample source code into your program(s) without
//**                 restriction.  This sample source code has been provided "AS IS" and the
//**                 responsibility for its operation is yours.  You are not permitted to
//**                 redistribute this sample source code as "Eleven sample source code" after
//**                 having made changes.  If you are going to re-distribute the source, we require
//**                 that you make it clear in the source that the code was descended from Eleven
//**                 sample source code, but that you have made changes.
//**
//*************************************************************************************************
//*************************************************************************************************
//**
//**	UnsignedDivide
//**
//*************************************************************************************************
//*************************************************************************************************

#ifndef __MATH__
#define __MATH__

//=============================================================================
// Input Params:	r1 = Numerator (Unsigned 16-bit Integer)
//			r2 = Divisor (Unsigned 16-bit Integer)
// Output Params:	r1 = Result
//			r2 = Remainder
//-----------------------------------------------------------------------------
// Description:	Performs the unsigned integer division of one 16-Bit unsigned
//			integer by another 16-bit unsinged integer.
//
//			Note:  x/0 is treated as x/1 to prevent an infinite loop.
//
// 			There is some optimization in the register usage to be done 
//			but this routine is compatible with the old UnsignedDivide 
//			routine.  This version has some speed optimizations over the
//			previous version.
//=============================================================================
UnsignedDivide:
		st	r3, sp, 0
		st	r4, sp, 1
		st	r5, sp, 2
		add	sp, sp, 3

		// r1 = dividend / numerator / result
		// r2 = remainder
		// r3 = divisor
		// r4 = loop counter
		// r5 = carry

		mov	r4, 17				// Setup loop counter
		add	r3, r2, 0				// mov r3 = r2
		mov	r2, 0					// Clear remainder
		mov	r5, 0					// Clear carry

	UnsignedDivide_loop:	
		sub	r4, r4, 1				// Decrement loop counter
		bc	ZS, UnsignedDivide_done

		add	r1, r1, r1				// Shift left dividend into carry
		bc	CS, UnsignedDivide_carryset

	UnsignedDivide_carryclear:
		add	r1, r1, r5				// Add carry-in
		add	r2, r2, r2				// Shift leftremainder with no carry
		sub	r2, r2, r3				// Subtract divisor from remainder
		
		bc	ULT, UnsignedDivide_undo	// Check for negative result(CS)
		
		mov	r5, 1					// Set carry

		bra	UnsignedDivide_loop

	UnsignedDivide_undo:
		add	r2, r2, r3				// Add back divisor
		mov	r5, 0					// Clear carry

		bra	UnsignedDivide_loop

	UnsignedDivide_carryset:
		add	r1, r1, r5				// Add carry-in
		add	r2, r2, r2				// Shift left remainder
		add	r2, r2, 1				// Add carry
		sub	r2, r2, r3				// Subtract divisor from remainder
		bc	ULT, UnsignedDivide_undo	// Check for negative result(CS)
		mov	r5, 1					// Set carry

		bra	UnsignedDivide_loop

	UnsignedDivide_done:
		add	r1, r1, r1				// Shift left dividend
		add	r1, r1, r5				// Add carry-in

UnsignedDivide_END:
		sub	sp, sp, 3
		ld	r3, sp, 0
		ld	r4, sp, 1
		ld	r5, sp, 2
		jsr	r6, r6
		
#endif